﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;

namespace Dycox.Drawing
{
    [TypeConverter(typeof(PaddingsConverter))]
    public struct Paddings
    {
        public static readonly Paddings Empty = new Paddings();

        public Paddings(float all)
            : this(all, all, all, all)
        {

        }

        public Paddings(float left, float top, float right, float bottom)
        {
            _left = left;
            _top = top;
            _right = right;
            _bottom = bottom;
        }

        private float _left, _top, _right, _bottom;

        public float Left
        {
            get { return _left; }
            set { _left = value; }
        }

        public float Top
        {
            get { return _top; }
            set { _top = value; }
        }

        public float Right
        {
            get { return _right; }
            set { _right = value; }
        }

        public float Bottom
        {
            get { return _bottom; }
            set { _bottom = value; }
        }

        public bool IsEmpty
        {
            get
            {

                float d = default(float);

                return _left == d && _right == d && _top == d && _bottom == d;
            }
        }

        public RectangleF Deflect(RectangleF rect)
        {
            return new RectangleF(
                rect.Left + _left,
                rect.Top + _top,
                rect.Width - (_left + _right),
                rect.Height - (_top + _bottom));
        }

        public override string ToString()
        {
            return string.Concat(
                _left.ToString("0.##"),
                Delimiter,
                _top.ToString("0.##"),
                Delimiter,
                _right.ToString("0.##"),
                Delimiter,
                _bottom.ToString("0.##"));
        }

        const char Delimiter = ',';

        public static bool TryParse(string text, out Paddings value)
        {
            value = Empty;

            if (!string.IsNullOrWhiteSpace(text))
            {
                string[] parts = text.Split(Delimiter);
                int length = parts.Length;
                float[] values = new float[4];

                for (int i = 0; i < 4; i++)
                {
                    string t;

                    if (i < length)
                    {
                        t = parts[i].Trim();
                        if (t.Length > 0)
                        {
                            float f;

                            if (float.TryParse(t, out f))
                                values[i] = f;
                            else
                                return false;
                        }
                    }
                }

                value = new Paddings(values[0], values[1], values[2], values[3]);
            }

            return true;

        }

        public static Paddings Parse(string text)
        {
            Paddings p;

            if (TryParse(text, out p))
                return p;

            throw new ArgumentException();
        }

        // override object.Equals
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }

            Paddings other = (Paddings)obj;

            return Equals(other);
        }

        private bool Equals(Paddings other)
        {
            return
                other._bottom == _bottom &&
                other._left == _left &&
                other._right == _right &&
                other._top == _top;
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return _left.GetHashCode() ^ _top.GetHashCode() ^ _right.GetHashCode() ^ _bottom.GetHashCode();
        }

        public static bool operator ==(Paddings v1, Paddings v2)
        {
            return v1.Equals(v2);
        }

        public static bool operator !=(Paddings v1, Paddings v2)
        {
            return !v1.Equals(v2);
        }
    }

    
    public class PaddingsConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                return Paddings.Parse((string)value);
            }
            return base.ConvertFrom(context, culture, value);
        }
    }
}
